﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ObserverAsync
{
    /// <summary>
    /// 抽象观察
    /// </summary>
    public abstract class Observer
    {
        public abstract Task UpdateAsync();
    }

    /// <summary>
    /// 短信观察者
    /// </summary>
    public class MessageObserver : Observer
    {
        public Subject Subject { get; set; }

        public MessageObserver(Subject subject)
        {
            Subject = subject;
        }

        public override Task UpdateAsync()
        {
            Console.WriteLine($"{Subject.State}:短信通知了...");
            return Task.CompletedTask;
        }
    }

    /// <summary>
    /// 积分观察者
    /// </summary>
    public class BonusObserver : Observer
    {
        public Subject Subject { get; set; }

        public BonusObserver(Subject subject)
        {
            Subject = subject;
        }

        public override Task UpdateAsync()
        {
            Console.WriteLine($"{Subject.State}:积分增加了...");
            return Task.CompletedTask;
        }
    }

    /// <summary>
    /// 券观察者
    /// </summary>
    public class CouponObserver : Observer
    {
        public Subject Subject { get; set; }

        public CouponObserver(Subject subject)
        {
            Subject = subject;
        }

        public override async Task UpdateAsync()
        {
            Console.WriteLine($"{Subject.State}:开始制券...");
            //模拟制券耗时
            await Task.Delay(3000);
            Console.WriteLine($"{Subject.State}:制券完成...");
        }
    }

    /// <summary>
    /// 抽象通知者
    /// </summary>
    public abstract class Subject
    {
        /// <summary>
        /// 观察者集合
        /// </summary>
        protected List<Observer> observers = new List<Observer>();

        public string State { get; set; }

        /// <summary>
        /// 添加观察者
        /// </summary>
        /// <param name="observer">观察者</param>
        public void Attach(Observer observer)
        {
            observers.Add(observer);
        }

        /// <summary>
        /// 删除观察者
        /// </summary>
        /// <param name="observer">观察者</param>
        public void Detach(Observer observer)
        {
            observers.Remove(observer);
        }

        /// <summary>
        /// 通知
        /// </summary>
        /// <returns></returns>
        public Task Notify()
        {
            foreach (var observer in observers)
            {
                observer.UpdateAsync();
            }
            return Task.CompletedTask;
        }
    }

    /// <summary>
    /// 支持成功通知者
    /// </summary>
    public class PaySuccessSubject : Subject
    {
    }
}